import React, { Component } from 'react'


class Child extends Component {
    constructor() {
        super();
        this.state = {
            name: "jack"
        }
    }
    render() {
        return (
            <div>child</div>
        )
    }

    childFn() {
        console.log(this.state.name);
    }
}

export class RefCom extends Component {
    constructor() {
        super();
        this.state = {
            el: React.createRef(),
            elFn: null
        }
    }
    render() {
        return (
            <div>
                {/* 如何创建refs来获取对应的DOM呢？目前有三种方式：
                方式一：传入字符串
                使用时通过 this.refs.传入的字符串格式获取对应的元素；
                方式二：传入一个对象
                对象是通过 React.createRef() 方式创建出来的；
                使用时获取到创建的对象其中有一个current属性就是对应的元素；
                方式三：传入一个函数
                该函数会在DOM被挂载时进行回调，这个函数会传入一个 元素对象，我们可以自己保存；
                使用时，直接拿到之前保存的元素对象即可； */}
                <div ref="title">title</div>
                <div ref={this.state.el}>title</div>
                <div ref={(element) => { this.state.elFn = element }}>title</div>
                <button onClick={this.change.bind(this)}>change</button>
                {/* ref 的值根据节点的类型而有所不同：
                当 ref 属性用于 HTML 元素时，构造函数中使用 React.createRef() 创建的 ref 接收底层 DOM 元素作为其 current 属性；
                当 ref 属性用于自定义 class 组件时，ref 对象接收组件的挂载实例作为其 current 属性；
                你不能在函数组件上使用 ref 属性，因为他们没有实例；
                这个时候我们可以通过 React.forwardRef  */}
                {/* React 会在组件挂载时给 current 属性传入 DOM 元素，并在组件卸载时传入 null 值。ref 会在 componentDidMount 或 componentDidUpdate 生命周期钩子触发前更新。 */}
                <Child ref="child" />
            </div>
        )
    }
    change() {
        this.refs.title.innerHTML = "获取DOM节点";
        this.state.el.current.innerHTML = "获取DOM节点";
        this.state.elFn.innerHTML = "获取DOM节点";
        this.refs.child.childFn();
    }
}


////React.forwardRef的使用
// Ref 转发是一项将 ref 自动地通过组件传递到其一子组件的技巧。
// 这样在父组件中就可以获取到子组件中的节点了。

import React, { PureComponent } from 'react'

const FnRef = React.forwardRef((props, ref) => {
    return (
        <button ref={ref}>ref转发</button>
    )
})

export default class AB extends PureComponent {

    constructor(props) {
        super(props);
        this.state = {
            refFn: React.createRef()
        }
    }

    getChildBtn() {
        console.log(this.state.refFn.current);
    }

    render() {
        return (
            <div>
                {/* 如果不通过ref转发，传递给子组件的ref属性，子组件通过props是获取不到的。 */}
                {/* 不通过ref转发，函数组件没有实例，不能直接使用ref */}
                <FnRef ref={this.state.refFn}></FnRef>
                <button onClick={() => { this.getChildBtn() }}>获取子组件的button元素</button>
            </div>
        )
    }
}